package com.fenghen.aspect;

import com.fenghen.entity.Test;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Before;
import org.springframework.stereotype.Component;

import java.util.Date;

// 使用@Component注解声明这是一个Spring组件，Spring会自动扫描并管理此类的实例
@Component
// 使用@Aspect注解声明这是一个切面类，用于定义横切关注点（如日志、事务等）
@Aspect
// 使用@Slf4j注解来自动生成日志对象log，方便进行日志记录
@Slf4j
public class TimeAspect {

    // 定义一个环绕通知，针对com.aopdemo.service包下的所有类的所有方法
    @Around("execution(* com.fenghen.service.*.*(..))")
    public Object recordTime(ProceedingJoinPoint pjp) throws Throwable {
        // 记录方法执行的开始时间
        long begin = System.currentTimeMillis();

        // 执行被拦截的方法，并获取其返回结果
        // ProceedingJoinPoint接口提供了对连接点进行操作的能力，这里用来调用目标方法
        Object result = pjp.proceed();

        // 记录方法执行的结束时间
        long end = System.currentTimeMillis();

        // 计算方法执行的总耗时
        // pjp.getSignature()可以获得被拦截方法的签名信息，包括类名和方法名等
        log.info(pjp.getSignature() + "执行耗时: {}毫秒", end - begin);

        // 返回被拦截方法的原始返回值
        return result;
    }

    @Before("execution(* com.fenghen.service.*.save*(..)) || execution(* com.fenghen.service.*.update*(..))")
    public void beforeSaveOrUpdate(JoinPoint joinPoint) {
        Object[] args = joinPoint.getArgs();
        for (Object arg : args) {
            if (arg instanceof Test) {
                Test entity = (Test) arg;
                Date now = new Date();
                if (entity.getCreatetime() == null) {
                    entity.setCreatetime(now);
                }
                entity.setUpdatetime(now);
            }
        }
    }
}
